1.身份验证
2.授权
三种方法:编程,注解,jsp
3.加密
4.会话管理
1.subject 用户
2.securityManager
安全管理器 是shiro的核心就行dispacher servlet 是 springmvc的核心
3.realm 域
shiro从realm获取安全数据(用户,角色,权限),类似数据源
shiro不能自己维护用户,角色等信息,是通过realm让程序员自己注入。
1.先从servlet开始
public class LoginServlet extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("login doget");
req.getRequestDispatcher("login.jsp").forward(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("login dopost");
String userName = req.getParameter("userName");
String password = req.getParameter("password");
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token= new UsernamePasswordToken(userName,password);
try{
subject.login(token);
Session session= subject.getSession();
System.out.println(session.getId());
System.out.println(session.getHost());
System.out.println(session.getTimeout());
resp.sendRedirect("success.jsp");
}catch (Exception e){
e.printStackTrace();
req.setAttribute("errorInfo","用户名密码错误");
req.getRequestDispatcher("login.jsp").forward(req,resp);
}
}
}
~1 从request中获得登录名和密码
~2 用用户名密码生成token
~3 从SecurityUtils中获得用户,SecurityUtils比securityManager要大
~4 可以用subject,token登录 subject.login(token); subject的login是shiro框架里的,不用自己写。
~5 可以用subject获取session
2.login方法会跳到realm域中 realm调dao层,其中用到了数据库的连接
public class MyRealm extends AuthorizingRealm{
private UserDao userDao = new UserDao();
private DbUtil dbUtil = new DbUtil();
//为登录用户授权 第7讲20分钟
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
String userName = (String) principalCollection.getPrimaryPrincipal();
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
Connection con = null;
try{
con=dbUtil.getCon();
//设置角色
authorizationInfo.setRoles(userDao.getRoles(con,userName));
//设置权限
authorizationInfo.setStringPermissions(userDao.getPermission(con,userName));
}catch (Exception e){
e.printStackTrace();
}finally {
try {
dbUtil.closeCon(con);
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
// 验证当前登录用户
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
String userName = (String) token.getPrincipal();
Connection con = null;
try{
con=dbUtil.getCon();
User user = userDao.getByUserName(con,userName);
if(user != null){
AuthenticationInfo authcInfo = new SimpleAuthenticationInfo(user.getUserName(),user.getPassWord(),"xx");
return authcInfo;
}
else{
return null;
}
}catch (Exception e){
e.printStackTrace();
}finally {
try{
dbUtil.closeCon(con);
}catch (Exception e){
e.printStackTrace();}
}
return null;
}
}
@1 登录
~1token中获得subject的userName
~2 dbUtil获得数据库连接
~3 用连接和userName访问dao
~4 获得身份验证AuthenticationInfo
@2 授权
~1 用连接和userName从dao中查到角色赋给授权info AuthorizationInfo
~2 用连接和userName从dao中查到权限赋给授权info AuthorizationInfo
public class UserDao {
public User getByUserName(Connection con, String userName) throws Exception{
User resultUser = null;
String sql = "select * from t_user where userName = ?";
PreparedStatement pstmt = con.prepareStatement(sql);
pstmt.setString(1,userName);
ResultSet rs = pstmt.executeQuery();
if(rs.next()){
resultUser = new User();
resultUser.setId(rs.getInt("id"));
resultUser.setUserName(rs.getString("userName"));
resultUser.setPassWord(rs.getString("passWord"));
}
return resultUser;
}
}
~1 连接和sql结合生产PreparedStatement
~2 给PreparedStatement设置参数
~3 PreparedStatement执行查询executeQuery()
4. dbUtil 连接数据库
public class DbUtil {
public Connection getCon()throws Exception{
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/relationship","root","123");
return con;
}
public void closeCon(Connection con) throws Exception{
con.close();
}
~1 映射获得jdbcDriver的类
~2 DriverManager用驱动管理器连接的,参数传入数据库连接地址,用户名,密码
逻辑和一般应用的差不多,从servlet开始,拿着参数查询数据库对比是否一致或赋值。但是好多方法都是框架的,特色比如realm,还有数据库的连接方式等。
shiro可以实现单点登录,用户访问数量的控制。