springboot integration shiro rights management

Inner monologue: blog empty window for six months, which experience sure to remember, just want to adjust the attitude continue to do so, taking advantage of young, fight it! ! !

Background: springboot2.1, shiro1.4; due to the current small projects do not log in, but they need to add client permissions, the landlord thought of shiro (This is a separate project, need to integrate back office systems)

shiro 简介

Apache Shiro is a Java security framework, integration is relatively simple, can help us to complete the authentication, authorization, encryption, session management, integration with Web, caching.

Authentication : authentication / login, verify that the user is not have the appropriate identification;

The Authorization : Authorization that the competence to verify, verify that a user has authenticated a privilege; that is, whether the user can do things such as common: verify that a user has a role. Or fine-grained verify whether a user has a permission for a resource;

Subject : subject, it represents the current "user", the user is not necessarily a specific person, and any current stuff is Subject interactive applications, such as web crawlers, robots; that is an abstract concept; all are bound to the Subject SecurityManager, all interactions with the Subject will be entrusted to the SecurityManager; Subject can be considered a facade; SecurityManager is the actual performer;

SecurityManager : security manager; that is, all safety-related operations will interact with the SecurityManager; and it manages all Subject; we can see it is the core of Shiro, which is responsible for interacting with other components behind the introduction of, if studied SpringMVC, you can see it as DispatcherServlet front controller;

Realm : domain, Shiro acquired from safety data (such as users, roles, permissions) from the Realm, that is SecurityManager to authenticate users, it needs to obtain the appropriate user from the Realm are compared to determine the identity of the user is legitimate; need from the Realm to give the user the role / permissions to verify that the user can operate; can Realm as dataSource, i.e. secure data source.

The above paragraph is the online copy of this (reference address: https://jinnianshilongnian.iteye.com/blog/2018936 )

Following the introduction of their actual code

Log entry:

Re-built a AuthenticationToken subclass TenantUsernamePasswordToken add a variable tenantId

@RequestMapping("/login")
    @ResponseBody
    public GlobalResult loginUser(String loginName,String password,HttpServletRequest request) {
        AuthenticationToken usernamePasswordToken = new TenantUsernamePasswordToken(loginName,tenantId,password);
        Subject subject = SecurityUtils.getSubject();
        try {
            subject.login(usernamePasswordToken);   //完成登录
            User user = (User) subject.getPrincipal();
            subject.getSession().setTimeout(60*60000);//1h过期(ms)
            subject.getSession().setAttribute("user", user);
            return ResultUtil.success();
        } catch (IncorrectCredentialsException e) {
            return ResultUtil.fail ( "wrong password");
        The catch} (LockedAccountException E) { 
            return ResultUtil.fail ( "login fails, the user has been frozen"); 
        } the catch (of AuthenticationException E) { 
            return ResultUtil.fail ( "the user does not exist"); 
        } the catch (Exception E) { 
            e.printStackTrace (); 
            return ResultUtil.fail ( "login exception because: {}" + e.getMessage ()); 
        } 
    }  

The next major configuration posted shiro

TenantUsernamePasswordToken

public class TenantUsernamePasswordToken extends UsernamePasswordToken {
    private static final long serialVersionUID = 3814343176522955308L;
    private String tenant;

    public TenantUsernamePasswordToken() {
    }

    public TenantUsernamePasswordToken(String username, String tenant, char[] password) {
        this(username, tenant, (char[])password, false, (String)null);
    }

    public TenantUsernamePasswordToken(String username, String tenant, String password) {
        this(username, tenant, (char[])(password != null?password.toCharArray():null), false, (String)null);
    }

    public TenantUsernamePasswordToken(String username, String tenant, char[] password, String host) {
        this(username, tenant, password, false, host);
    }

    public TenantUsernamePasswordToken(String username, String tenant, String password, String host) {
        this(username, tenant, password != null?password.toCharArray():null, false, host);
    }

    public TenantUsernamePasswordToken(String username, String tenant, char[] password, boolean rememberMe) {
        this(username, tenant, (char[])password, rememberMe, (String)null);
    }

    public TenantUsernamePasswordToken(String username, String tenant, String password, boolean rememberMe) {
        this(username, tenant, (char[])(password != null?password.toCharArray():null), rememberMe, (String)null);
    }

    public TenantUsernamePasswordToken(String username, String tenant, String password, boolean rememberMe, String host) {
        this(username, tenant, password != null?password.toCharArray():null, rememberMe, host);
    }

    public TenantUsernamePasswordToken(String username, String tenant, char[] password, boolean rememberMe, String host) {
        super(username, password, rememberMe, host);
        this.tenant = tenant;
    }

    public String getTenant() {
        return this.tenant;
    }

    public void setTenant(String tenant) {
        this.tenant = tenant;
    }

    public void clear() {
        super.clear();
        this.tenant = null;
    }

    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(this.getClass().getName());
        sb.append(" - ");
        sb.append(this.getUsername());
        sb.append(", tenant=").append(this.tenant);
        sb.append(", rememberMe=").append(this.isRememberMe());
        if(this.getHost() != null) {
            sb.append(" (").append(this.getHost()).append(")");
        }

        return sb.toString();
    }
}

A newly defined password comparator (prepared according to the service may require their own)

CredentialsMatcher the extends SimpleCredentialsMatcher {class public 

    @Override 
    public Boolean doCredentialsMatch (AuthenticationToken token, AuthenticationInfo info) { 
        UsernamePasswordToken utoken = (UsernamePasswordToken) token; 
        // get the password entered by the user :( salt (salt) methods can be used to test) 
        String inPassword new new String = (utoken.getPassword ()); 
        // get the password database 
        String dbPassword = (String) info.getCredentials ( ); 
        ratio of // password 
// return this.equals (inPassword, dbPassword) ; ignore password comparison 
        return to true; 
    }

AuthRealm (log check, assign permissions, etc.) 

public class AuthRealm extends AuthorizingRealm {

    @Autowired
    private IUserService userService;


    /**
     * 授权
     * @param principal
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {
        System.err.println("===================================================================================");
        if(principal == null) {
            throw new AuthorizationException("PrincipalCollection method argument cannot be null.");
        } else {
            User userInfo = (User)this.getAvailablePrincipal(principal);
            log.info("username:{},userId:{}", userInfo.getLoginName(), userInfo.getId());
            Set<String> permissions = new HashSet();
            List<Resource> resourceList = this.userService.findResourcesByUserId(userInfo.getId());
            if(resourceList.isEmpty()) {
                log.error("current user:{} has not resources ", userInfo.getLoginName());
                return null;
            } else {
                Iterator i$ = resourceList.iterator();
                while(i$.hasNext()) {
                    Resource resource = (Resource)i$.next();
                    String permission = resource.getCode();
                    if(StringUtil.isNotEmpty(permission) && !permissions.contains(permission)) {
                        permissions.add(permission);
                    }
                }

                SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
                authorizationInfo.setStringPermissions(permissions);
                return authorizationInfo;
            }
        }
    }

    /**
     * 认证登录
     * @param token
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        TenantUsernamePasswordToken utoken = (TenantUsernamePasswordToken) token;//获取用户输入的token
        String userName = utoken.getUsername();
        String tenantId = utoken.getTenant();
        User user;
        try {
            user = userService.getByLoginNameAndTenantId(userName,tenantId);
        } catch (Exception var8) {
            log.error("无法获取用户信息!", var8);
            throw new UnknownAccountException(SpringContextUtils.getMessage("security.usernameNotExists"), var8);
        }
        if(user == null) {
            throw new UnknownAccountException(SpringContextUtils.getMessage("security.usernameNotExists"));
        } else {
            return new SimpleAuthenticationInfo (user, null, this.getClass () getName ().); // put shiro call CredentialsMatcher test password. 
        } 
    } 

} 

 ShiroConfiguration (main configuration)

@Configuration 
public class ShiroConfiguration { 


    / ** 
     * anon anonymous access 
     * authc landed access 
     * @param Manager 
     * @return 
     * / 
    @Bean (name = "shiroFilter") 
    public ShiroFilterFactoryBean shiroFilter (@ Qualifier ( "securityManager") the SecurityManager Manager) { 
        bean = new new ShiroFilterFactoryBean ShiroFilterFactoryBean (); 
        bean.setSecurityManager (Manager); 
        // url and configured to log successful login url 
        bean.setLoginUrl ( "/ unlogin"); 
// bean.setSuccessUrl ( "/ Merchant / Home");  
        // configure access 
        LinkedHashMap <String, String> filterChainDefinitionMap = new LinkedHashMap <> ();
        filterChainDefinitionMap.put ( "/ static / **" , "anon"); // static resources does not intercept 
        filterChainDefinitionMap.put ( "/login",  "anon");
        filterChainDefinitionMap.put ( "/ **", "authc"); 
        bean.setFilterChainDefinitionMap (filterChainDefinitionMap); 
        return the bean; 
    } 

    / ** 
     * core security transaction manager configured 
     * @param authRealm 
     * @return 
     * / 
    @Bean (name = "securityManager") 
    public securityManager the securityManager (@Qualifier ( "authRealm") authRealm authRealm) { 
        System.err.println ( "Shiro has been loaded -------------- ------- --------- "); 
        DefaultWebSecurityManager Manager new new DefaultWebSecurityManager = ();  
        manager.setRealm (authRealm);
        return manager;
    }

    / ** 
     * configure a custom permission logger 
     * @param Matcher 
     * @return 
     * / 
    @Bean (name ="authRealm ")
    AuthRealm authRealm public (@Qualifier ( "credentialsMatcher") CredentialsMatcher Matcher) { 
        AuthRealm authRealm new new AuthRealm = (); 
        authRealm.setCredentialsMatcher (Matcher); 
        return authRealm; 
    } 

    / ** 
     * custom configuration password comparator 
     * @return 
     * / 
    @Bean (name = "credentialsMatcher") 
    public CredentialsMatcher credentialsMatcher () { 
        return new new CredentialsMatcher (); 
    }  
    @Bean 
    public lifecycleBeanPostProcessor lifecycleBeanPostProcessor () {
        return new new LifecycleBeanPostProcessor (); 
    } 

    / ** 
     * open shiro annotation 
     * @return 
     * / 
    @Bean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator(){
        DefaultAdvisorAutoProxyCreator creator=new DefaultAdvisorAutoProxyCreator();
        creator.setProxyTargetClass(true);
        return creator;
    }

    /**
     * 开启aop
     * @param manager
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("securityManager") SecurityManager manager) {
        AuthorizationAttributeSourceAdvisor advisor=new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(manager);
        return advisor;
    }

    /**
     * 注册全局异常处理
     * @return
     */
    @Bean(name = "exceptionHandler")
    public HandlerExceptionResolver handlerExceptionResolver() {
        return new MyExceptionHandler();
    }

}

  This main configuration code have been completed (to facilitate future records for personal use --- mainly for reference only)

If you want to control permissions on an interface shiro label (the following code example) you need to be added on the desired interface

    @ RequestMapping ( "/ getUser") 
    @ResponseBody 
    @RequiresPermissions ( "/ getUser") // This is the resource name stored in the database of 
    public GlobalResult getUser (loginName String, String password, the HttpSession the session) { 
        return ResultUtil.success (userService.getByLoginNameAndTenantId ( "zhangsan", TenantID)); 
    }

  

 

 

 

 

 

  

Guess you like

Origin www.cnblogs.com/chenpt/p/11068380.html