Shiro(2)

Shiro

1 自定义realm,认证,授权

所需要pom的依赖:shiro-core, shiro-spring, mybatis-spring-boot-starter, mysql-connector-java, spring-boot-starter-thymeleaf, aspectjweaver
application.yml配置文件

mybatis:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.java502.shirodemo502.pojo
spring:
  datasource:
    type: com.zaxxer.hikari.HikariDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/shrio?useUnicode=true&characterEncoding=utf8
    username: root
    password: 123123

MyRealm.java

@Component
public class MyRealm extends AuthorizingRealm {
    @Autowired
    private UserService userService;
    // 授权的方法
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        // 去数据库(Redis)
        // 拿到用户名
        String  userName = (String) principalCollection.getPrimaryPrincipal();
        // 获取用户对象
        User user = getUserByUserName(userName);
        // 获取权限信息
        Set<String> permissions = getPermissionByUser(user);
        // 获取角色数据
        Set<String> roles = getRoleByUser(user);
        // 返回授权信息
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        authorizationInfo.setStringPermissions(permissions);
        authorizationInfo.setRoles(roles);
        return authorizationInfo;
    }
    /**
     * 获取角色数据
     */
    private Set<String> getRoleByUser(User user) {
        Set<String> roles = new HashSet<>();
        roles.add(user.getRole().getRoleName());
        return roles;
    }
    /**
     * 获取权限数据
     */
    private Set<String> getPermissionByUser(User user) {
        Set<String> permissions = new HashSet<>();
        // 获取权限列表
        List<Access> accessList = user.getRole().getAccessList();
        for (Access access : accessList) {
            permissions.add(access.getAccessUrl());
        }
        return permissions;
    }
    /**
     * 获取用户对象
     */
    private User getUserByUserName(String userName) {
        if(userName == null || userName.isEmpty()){
            return null;
        }
        return userService.getUser(userName);
    }
    /**
     * 认证的方法(登陆)
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        // 通过token去获取用户名
        String userName = (String) authenticationToken.getPrincipal();
        // 通过查询数据库得到对应的用户信息
        String pwd = getPwdByUserName(userName);
        if (pwd == null) {
            return null;
        }
        // 认证信息
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(userName, pwd, "myRealm");
        // 设置加盐
        info.setCredentialsSalt(ByteSource.Util.bytes("java502"));
        return info;
    }
    /**
     * 通过用户名查询用户密码
     */
    private String getPwdByUserName(String userName) {
        if(userName == null || userName.isEmpty()) {
            return null;
        }
        User user = userService.getUser(userName);
        if(user == null) {
            return null;
        }
        return user.getUserPwd();
    }
}

RoleMapper.java:Role findById(@Param(“roleId”) Integer roleId);
RoleAccessMapper.java:List< Access> findAccessByRoleId(@Param(“roleId”) Integer roleId);
UserMapper.java

@Mapper
public interface UserMapper {
    /**
     * 查询所有
     */
    List<User> findAll();
    /**
     * 通过用户名来查询用户信息
     */
    User findByUserName(@Param("userName") String userName);
}

UserMapper.xml

<select id="findAll" resultType="com.java502.shirodemo502.pojo.User">
        select * from user
</select>
<resultMap id="userMap" type="com.java502.shirodemo502.pojo.User">
        <id property="id" column="id"/>
        <result property="userName" column="userName"/>
        <result property="userPwd" column="userPwd"/>
        <result property="userPhone" column="userPhone"/>
        <result property="userAddTime" column="userAddTime"/>
        <result property="roleId" column="roleId"/>
        <association property="role" column="roleId" javaType="com.java502.shirodemo502.pojo.Role" select="com.java502.shirodemo502.dao.RoleMapper.findById"/>
</resultMap>
    <!--通过用户名查询信息-->
<select id="findByUserName" resultMap="userMap">
	select * from user where userName=#{userName}
</select>

UserServiceImpl.java

@Service
@Transactional(rollbackFor = Exception.class)
@SuppressWarnings("all")
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;
    @Override
    public User getUser(String userName) {
        return userMapper.findByUserName(userName);
    }
}

登录案例

自带退出功能:

<a th:href="@{/logout}">退出</a>

注解权限控制

2 加密,过滤器,记住我的功能

自带的
自定义过滤器

@Configuration
public class ShiroConfig {
    /**
     * 加密算法
     */
    @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher(){
        HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
        matcher.setHashAlgorithmName("md5");
        matcher.setHashIterations(1);
        return matcher;
    }
    /**
     * 自定义realm
     */
    @Bean
    public MyRealm myRealm1(){
        MyRealm myRealm = new MyRealm();
        myRealm.setCredentialsMatcher(hashedCredentialsMatcher());
        return myRealm;
    }
    /**
     * 安全管理器
     */
    @Bean
    public SecurityManager securityManager(){
        // web环境的安全管理器
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(myRealm1());
        // 设置记住我
        securityManager.setRememberMeManager(rememberMeManager());
        return securityManager;
    }
    /**
     * shiro的过滤器
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean() {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        // 设置安全管理器
        shiroFilterFactoryBean.setSecurityManager(securityManager());
        // 配置拦截器
        // 配置不会被拦截的链接 顺序判断,因为前端模板采用了 thymeleaf,
        Map<String,String> filterChainDefinitionMap = new HashMap<>(16);
        // 这里不能直接使用 ("/static/**", "anon")来配置匿名访问,必须配置到每个静态目录
        filterChainDefinitionMap.put("/css/**", "anon");
        filterChainDefinitionMap.put("/fonts/**", "anon");
        filterChainDefinitionMap.put("/img/**", "anon");
        filterChainDefinitionMap.put("/js/**", "anon");
        //配置退出 过滤器,其中的具体的退出代码 Shiro 已经替我们实现了
        filterChainDefinitionMap.put("/logout", "logout");
        // 过滤链定义,从上向下顺序执行,一般将/**放在最为下边 -->:这是一个坑呢,一不小心代码就不好使了;
        // authc:所有 url 都必须认证通过才可以访问; anon:所有 url 都都可以匿名访问-->
        filterChainDefinitionMap.put("/user/login","anon");
        filterChainDefinitionMap.put("/user/login_page","anon");
        filterChainDefinitionMap.put("/member/testRole","roles[学生管理]");
       filterChainDefinitionMap.put("/member/testPer","permsOr[member:testPer,member:testPer2]");
        // 其余所有的访问都需要认证(登陆才可以访问)
        filterChainDefinitionMap.put("/**", "user");
        // 如果不设置默认会自动寻找 Web 工程根目录下的"/login.jsp"页面
        shiroFilterFactoryBean.setLoginUrl("/user/login_page");
        // 登录成功后要跳转的链接
        shiroFilterFactoryBean.setSuccessUrl("/index");
        //未授权界面;
        shiroFilterFactoryBean.setUnauthorizedUrl("/403");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        //注入自定义的filter
        // 用一个map来装自定义的filter
        Map<String, Filter> filterMap = new HashMap<>(16);
        filterMap.put("permsOr",permsOr());
        // 交给shiroFilterFactoryBean
        shiroFilterFactoryBean.setFilters(filterMap);
        return shiroFilterFactoryBean;
    }
    // 自定义的filter or
    @Bean
    public PermsOrFilter permsOr(){
        return new PermsOrFilter();
    }
    // cookie对象
    @Bean
    public SimpleCookie cookie(){
        // 创建cookie对象
        SimpleCookie cookie = new SimpleCookie();
        // 设置时间
        cookie.setMaxAge(3600);
        cookie.setName("hsj");
        return cookie;
    }
    // 记住我的管理器
    @Bean
    public CookieRememberMeManager rememberMeManager(){
        CookieRememberMeManager rememberMeManager = new CookieRememberMeManager();
        // 设置cookie
        rememberMeManager.setCookie(cookie());
        // 设置加密
        rememberMeManager.setCipherKey(Base64.decode("cXdlcnQxMjNxd2VydDEyMw=="));
        return rememberMeManager;
    }
    // 管理shiro相关bean的声明周期
    @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor(){
        return new LifecycleBeanPostProcessor();
    }
    // 切面的代理
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager);
        return advisor;
    }
}

PermsOrFilter .java

// or 的权限过滤器
public class PermsOrFilter extends AuthorizationFilter {
    @Override
    protected boolean isAccessAllowed(ServletRequest servletRequest, ServletResponse servletResponse, Object o) throws Exception {
        // 获取主体
        Subject subject = SecurityUtils.getSubject();
        // 得到权限数组
        String[] perms = (String[]) o;
        // 判断权限是否为空
        if(perms == null || perms.length == 0){
            return true;
        }
        // or 的逻辑处理
        for (String perm : perms) {
            // 利用主体去判断是否有对应的权限
            if (subject.isPermitted(perm)) {
                return true;
            }
        }
        return false;  // 返回false 表示没有权限
    }
}
发布了79 篇原创文章 · 获赞 7 · 访问量 1821

猜你喜欢

转载自blog.csdn.net/weixin_45044097/article/details/103852450
今日推荐